package com.bringspring.system.base.controller;

import com.bringspring.common.base.ActionResult;
import com.bringspring.common.base.Page;
import com.bringspring.common.base.vo.DownloadVO;
import com.bringspring.common.base.vo.ListVO;
import com.bringspring.common.base.vo.PageListVO;
import com.bringspring.common.base.vo.PaginationVO;
import com.bringspring.common.config.ConfigValueUtil;
import com.bringspring.common.constant.MsgCode;
import com.bringspring.common.database.model.DbTableDataForm;
import com.bringspring.common.database.model.DbTableFieldModel;
import com.bringspring.common.database.model.DbTableModel;
import com.bringspring.common.exception.DataException;
import com.bringspring.common.util.FileUtil;
import com.bringspring.common.util.JsonUtil;
import com.bringspring.common.util.StringUtils;
import com.bringspring.common.util.XSSEscape;
import com.bringspring.common.util.enums.ModuleTypeEnum;
import com.bringspring.common.util.file.FileExport;
import com.bringspring.system.base.model.dbtable.DbTableCreate;
import com.bringspring.system.base.model.dbtable.DbTableForm;
import com.bringspring.system.base.model.dbtable.DbTableUpdate;
import com.bringspring.system.base.model.dbtable.vo.DbTableFieldSeleVO;
import com.bringspring.system.base.model.dbtable.vo.DbTableFieldVO;
import com.bringspring.system.base.model.dbtable.vo.DbTableInfoVO;
import com.bringspring.system.base.model.dbtable.vo.DbTableVO;
import com.bringspring.system.base.service.DbTableService;
import com.bringspring.system.base.util.JsonUtilEx;
import com.bringspring.system.print.entity.PrintDevEntity;
import com.google.common.base.CaseFormat;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.Valid;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 数据建模
 *
 * @author 开发平台组
 * @version V1.0.0
 * @copyright 股份有限公司
 * @date 2017年9月27日 上午9:18
 */
@Api(tags = "数据建模", value = "DataModel")
@RestController
@RequestMapping("/api/system/DataModel")
@Slf4j
public class DbTableController {

    @Autowired
    private DbTableService dbTableService;
    @Autowired
    private FileExport fileExport;
    @Autowired
    private ConfigValueUtil configValueUtil;

    /**
     * 列表
     *
     * @param id   连接id
     * @param page 关键词
     * @return 数据库表列表
     * @throws DataException ignore
     */
    @ApiOperation("获取数据库表列表")
    @GetMapping("/{id}/Tables")
    public ActionResult<ListVO<DbTableModel>> getList(@PathVariable("id") String id, Page page) throws DataException {
        String escape = XSSEscape.escape(id);
        List<DbTableModel> data = dbTableService.getList(escape).stream()
                // 过滤不符条件的元素
                .filter(t ->
                        // 三目运算
                        StringUtils.isNotEmpty(page.getKeyword())
                                ? t.getDescription().toLowerCase().contains(page.getKeyword().toLowerCase())
                                || t.getTable().toLowerCase().contains(page.getKeyword().toLowerCase())
                                : t.getTable() != null
                )
                // 排序
                .sorted(Comparator.comparing(DbTableModel::getTable)).collect(Collectors.toList());
        ListVO<DbTableModel> vo = new ListVO<>();
        vo.setList(data);
        return ActionResult.success(vo);
    }

    /**
     * 预览数据库表
     *
     * @param dbTableDataForm 查询条件
     * @param linkId          接Id
     * @param tableName       表名
     * @return 数据库表
     * @throws Exception ignore
     */
    @ApiOperation("预览数据库表")
    @GetMapping("/{linkId}/Table/{tableName}/Preview")
    public ActionResult<PageListVO<Map<String, Object>>> data(DbTableDataForm dbTableDataForm, @PathVariable("linkId") String linkId, @PathVariable("tableName") String tableName) throws Exception {
        String escape = XSSEscape.escape(linkId);
        String escapeTableName = XSSEscape.escape(tableName);
        List<Map<String, Object>> data = dbTableService.getData(dbTableDataForm, escape, escapeTableName);
        PaginationVO paginationVO = JsonUtilEx.getJsonToBeanEx(dbTableDataForm, PaginationVO.class);
        return ActionResult.page(data, paginationVO);
    }

    /**
     * 列表
     *
     * @param linkId    数据连接ID
     * @param tableName 表名
     * @return 列表
     * @throws DataException ignore
     */
    @GetMapping("/{linkId}/Tables/{tableName}/Fields/Selector")
    @ApiOperation("获取数据库表字段下拉框列表")
    public ActionResult<ListVO<DbTableFieldSeleVO>> selectorList(@PathVariable("linkId") String linkId, @PathVariable("tableName") String tableName) throws DataException {
        List<DbTableFieldModel> data = dbTableService.getFieldList(linkId, tableName);
        List<DbTableFieldSeleVO> vos = JsonUtil.getJsonToList(data, DbTableFieldSeleVO.class);
        ListVO<DbTableFieldSeleVO> vo = new ListVO<>();
        vo.setList(vos);
        return ActionResult.success(vo);
    }

    /**
     * 字段列表
     *
     * @param linkId    连接Id
     * @param tableName 表名
     * @param type      类型
     * @return 段列表
     * @throws DataException ignore
     */
    @ApiOperation("获取数据库表字段列表")
    @GetMapping("/{linkId}/Tables/{tableName}/Fields")
    public ActionResult<ListVO<DbTableFieldVO>> fieldList(@PathVariable("linkId") String linkId, @PathVariable("tableName") String tableName, String type) throws DataException {
        List<DbTableFieldModel> data = dbTableService.getFieldList(linkId, tableName);
        List<DbTableFieldVO> vos = JsonUtil.getJsonToList(data, DbTableFieldVO.class);
        for (DbTableFieldVO vo : vos) {
            if ("1".equals(type)) {
                String name = vo.getField().toLowerCase().replaceAll("f_", "");
                vo.setField(CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name));
            }
        }
        ListVO<DbTableFieldVO> vo = new ListVO<>();
        vo.setList(vos);
        return ActionResult.success(vo);
    }

    /**
     * 信息
     *
     * @param linkId    连接Id
     * @param tableName 表名
     * @return 表信息
     * @throws DataException ignore
     */
    @ApiOperation("获取数据表")
    @GetMapping("/{linkId}/Table/{tableName}")
    public ActionResult<DbTableVO> get(@PathVariable("linkId") String linkId, @PathVariable("tableName") String tableName) throws DataException {
        return ActionResult.success(getDbTable(linkId, tableName));
    }

    private DbTableVO getDbTable(String linkId, String tableName)throws DataException {
        DbTableModel dbTableModel = dbTableService.getList(linkId).stream().filter(m -> m.getTable().equals(tableName)).findFirst().orElse(null);
        DbTableVO dbTableVO = new DbTableVO();
        if(dbTableModel != null){
            //转换
            DbTableInfoVO tableInfo = JsonUtilEx.getJsonToBeanEx(dbTableModel, DbTableInfoVO.class);
            List<DbTableFieldModel> tableFieldList = dbTableService.getFieldList(linkId, tableName);
            List<DbTableFieldVO> fieldList = JsonUtil.getJsonToList(tableFieldList, DbTableFieldVO.class);
            dbTableVO.setTableFieldList(fieldList);
            dbTableVO.setTableInfo(tableInfo);
        }
        return dbTableVO;
    }

    /**
     * 新建表
     *
     * @param linkId 连接Id
     * @return ignore
     * @throws DataException ignore
     */
    @ApiOperation("新建")
    @PostMapping("{linkId}/Table")
    public ActionResult<String> create(@PathVariable("linkId") String linkId, @RequestBody @Valid DbTableCreate dbTableCreate) throws DataException {
        dbTableCreate.initCreate(linkId);
        int status = dbTableService.createTable(dbTableCreate);
        if (status == 1) {
            return ActionResult.success(MsgCode.SU001.get());
        } else if (status == 0) {
            return ActionResult.fail("表名称不能重复");
        } else {
            return ActionResult.fail("添加失败");
        }
    }

    /**
     * 更新
     *
     * @param linkId 连接Id
     * @return ignore
     * @throws DataException ignore
     */
    @ApiOperation("更新")
    @PutMapping("/{linkId}/Table")
    public ActionResult<String> update(@PathVariable("linkId") String linkId, @RequestBody @Valid DbTableUpdate dbTableUpdate) throws DataException {
        dbTableUpdate.initUpdate(linkId);
        String newTable = dbTableUpdate.getNewTable();
        String oldTable = dbTableUpdate.getOldTable();
        // 当修改表名时，验证是否与其他表名重名
        if (!newTable.equals(oldTable) && dbTableService.isExistByTableName(linkId, newTable)) {
            return ActionResult.fail("表名称不能重复");
        }
        dbTableService.update(dbTableUpdate);
        return ActionResult.success(MsgCode.SU004.get());
    }

    /**
     * 删除
     *
     * @param linkId    连接Id
     * @param tableName 表名
     * @return ignore
     * @throws DataException ignore
     */
    @ApiOperation("删除")
    @DeleteMapping("/{linkId}/Table/{tableName}")
    public ActionResult<String> delete(@PathVariable("linkId") String linkId, @PathVariable("tableName") String tableName) throws DataException {
        dbTableService.delete(linkId, tableName);
        return ActionResult.success(MsgCode.SU003.get());
    }





    /**
     * 导入
     *
     * @param linkId        连接id
     * @param multipartFile 文件
     * @return ignore
     * @throws DataException ignore
     */
    @ApiOperation("导入")
    @PostMapping(value = "/{linkId}/Action/Import", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public ActionResult<PageListVO<PrintDevEntity>> importData(@PathVariable String linkId, @RequestPart("file") MultipartFile multipartFile) throws DataException {
        //判断是否为.json结尾
        if (FileUtil.existsSuffix(multipartFile, ModuleTypeEnum.SYSTEM_DBTABLE.getTableName())) {
            return ActionResult.fail(MsgCode.IMP002.get());
        }
        //读取文件内容
        String fileContent = FileUtil.getFileContent(multipartFile, configValueUtil.getTemporaryFilePath());
        try {
            DbTableVO dbTableVO = JsonUtil.getJsonToBean(fileContent, DbTableVO.class);
            // 判断是否已存在此表
            String tableName = dbTableVO.getTableInfo().getTable();
            if (dbTableService.isExistByTableName(linkId, tableName)) {
                return ActionResult.fail("表名称不能重复");
            }
            DbTableCreate dbTableCreate = new DbTableCreate();
            BeanUtils.copyProperties(dbTableVO, dbTableCreate);
            DbTableForm dbTableForm = new DbTableForm();
            dbTableCreate.setDbLinkId(linkId);
            dbTableForm.setNewTable(tableName);
            dbTableForm.setTableName(tableName);
            dbTableCreate.setTableInfo(dbTableForm);
            dbTableCreate.initCreate(linkId);
            //保存此表
            int i = dbTableService.createTable(dbTableCreate);
            if (i == 1) {
                return ActionResult.success(MsgCode.IMP001.get());
            } else {
                return ActionResult.success("数据库表名重复");
            }
        } catch (Exception e) {
            throw new DataException(MsgCode.IMP004.get());
        }
    }

    /**
     * 导出
     *
     * @param tableName 表明
     * @param linkId    连接id
     * @return ignore
     */
    @ApiOperation("导出")
    @GetMapping("/{linkId}/Table/{tableName}/Action/Export")
    public ActionResult<DownloadVO> export(@PathVariable String tableName, @PathVariable String linkId) {
        DownloadVO downloadVO = null;
        try {
            DbTableVO dbTable = getDbTable(linkId, tableName);
            //导出文件
            downloadVO = fileExport.exportFile(dbTable, configValueUtil.getTemporaryFilePath(), dbTable.getTableInfo().getTable() + "_", ModuleTypeEnum.SYSTEM_DBTABLE.getTableName());
        } catch (DataException e) {
            e.printStackTrace();
        }
        return ActionResult.success(downloadVO);
    }
}
